/////////////////////////////////////////////////////////////////////////////
// Copyright (c) 1999, COAS, Oregon State University  
// ALL RIGHTS RESERVED.   U.S. Government Sponsorship acknowledged. 
//
// Please read the full copyright notice in the file COPYRIGHT
// in this directory.
//
// Author: Nathan Potter (ndp@oce.orst.edu)
//
//                        College of Oceanic and Atmospheric Scieneces
//                        Oregon State University
//                        104 Ocean. Admin. Bldg.
//                        Corvallis, OR 97331-5503
//         
/////////////////////////////////////////////////////////////////////////////
//
// Based on source code and instructions from the work of:
//
/////////////////////////////////////////////////////////////////////////////
// Copyright (c) 1998, California Institute of Technology.  
// ALL RIGHTS RESERVED.   U.S. Government Sponsorship acknowledged. 
//
// Please read the full copyright notice in the file COPYRIGHT
// in this directory.
//
// Author: Jake Hamby, NASA/Jet Propulsion Laboratory
//         Jake.Hamby@jpl.nasa.gov
/////////////////////////////////////////////////////////////////////////////
using System;
using System.IO;
using NDODS.DAP.BaseTypes;
using NDODS.DAP.Parser;

namespace NDODS.DAP.Server {
    /// <summary> Holds a DODS Server <code>Boolean</code> value.
    /// 
    /// </summary>
    /// <version>  $Revision: 1.21 $
    /// </version>
    /// <author>  ndp
    /// </author>
    /// <seealso cref="BaseType">
    /// </seealso>
    public abstract class SDBoolean : DBoolean, IServerMethods, IRelationalOps, ExprParserConstants {
        //UPGRADE_NOTE: Respective javadoc comments were merged.  It should be changed in order to comply with .NET documentation conventions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1199'"
        /// <summary>Get the value of the Read property.</summary>
        /// <returns> <code>true</code> if the variable has been read,
        /// <code>false</code> otherwise.
        /// </returns>
        /// <seealso cref="Read(string,object)">
        /// </seealso>
        /// <seealso cref="setRead(bool)">
        /// </seealso>
        /// <summary>Set the Read property. A normal variable is read using the
        /// <code>read()</code> method. Once read the <em>Read</em> property is
        /// <code>true</code>. Use this function to manually set the property
        /// value. By default this property is false.
        /// </summary>
        /// <param name="state"><code>true</code> if the variable has been read,
        /// <code>false</code> otherwise.
        /// </param>
        /// <seealso cref="isRead()">
        /// </seealso>
        /// <seealso cref="Read(string,object)">
        /// </seealso>
        public virtual bool IsRead {
            get { return (ReadMe); }

            set { ReadMe = value; }
        }

        private bool Project;
        private bool Synthesized;
        private bool ReadMe;

        /// <summary>Constructs a new <code>SDBoolean</code>. </summary>
        public SDBoolean() : base() {
            Project = false;
            Synthesized = false;
            ReadMe = false;
        }


        /// <summary> Constructs a new <code>SDBoolean</code> with name <code>n</code>.</summary>
        /// <param name="n">the name of the variable.
        /// </param>
        public SDBoolean(String n) : base(n) {
            Project = false;
            Synthesized = false;
            ReadMe = false;
        }

        /// <summary> Write the variable's declaration in a C-style syntax. This
        /// function is used to create textual representation of the Data
        /// Descriptor Structure (DDS).  See <em>The DODS User Manual</em> for
        /// information about this structure.
        /// 
        /// </summary>
        /// <param name="os">The <code>PrintWriter</code> on which to print the
        /// declaration.
        /// </param>
        /// <param name="space">Each line of the declaration will begin with the
        /// characters in this string.  Usually used for leading spaces.
        /// </param>
        /// <param name="print_semi">a bool value indicating whether to print a
        /// semicolon at the end of the declaration.
        /// </param>
        /// <param name="constrained">a bool value indicating whether to print
        /// the declartion dependent on the projection information. <b>This
        /// is only used by Server side code.</b>
        /// </param>
        /// <seealso cref="DDS">
        /// </seealso>
        public override void PrintDecl(StreamWriter os, String space, bool print_semi, bool constrained) {
            if (constrained && !Project)
                return;

            // BEWARE! Since printDecl()is (multiple) overloaded in BaseType
            // and all of the different signatures of printDecl() in BaseType
            // lead to one signature, we must be careful to override that
            // SAME signature here. That way all calls to printDecl() for 
            // this object lead to this implementation.

            // Also, since printDecl()is (multiple) overloaded in BaseType
            // and all of the different signatures of printDecl() in BaseType
            // lead to the signature we are overriding here, we MUST call
            // the printDecl with the SAME signature THROUGH the super class
            // reference (assuming we want the super class functionality). If
            // we do otherwise, we will create an infinte call loop. OOPS!

            base.PrintDecl(os, space, print_semi, constrained);
        }


        /// <summary> Prints the value of the variable, with its declaration.  This
        /// function is primarily intended for debugging DODS applications and
        /// text-based clients such as geturl.
        /// 
        /// <h2> Important Note</h2>
        /// This method overrides the BaseType method of the same name and 
        /// type signature and it significantly changes the behavior for all versions
        /// of <code>printVal()</code> for this type: 
        /// <b><i> All the various versions of printVal() will only
        /// print a value, or a value with declaration, if the variable is
        /// in the projection.</i></b>
        /// <br>
        /// <br>In other words, if a call to 
        /// <code>isProject()</code> for a particular variable returns 
        /// <code>true</code> then <code>printVal()</code> will print a value 
        /// (or a declaration and a value). 
        /// <br>
        /// <br>If <code>isProject()</code> for a particular variable returns 
        /// <code>false</code> then <code>printVal()</code> is basically a No-Op.
        /// <br>
        /// <br>
        /// 
        /// </summary>
        /// <param name="os">the <code>PrintWriter</code> on which to print the value.
        /// </param>
        /// <param name="space">this value is passed to the <code>printDecl</code> method,
        /// and controls the leading spaces of the output.
        /// </param>
        /// <param name="print_decl_p">a bool value controlling whether the
        /// variable declaration is printed as well as the value.
        /// </param>
        /// <seealso cref="BaseType.printVal(StreamWriter, String, bool)">
        /// </seealso>
        /// <seealso cref="IServerMethods.IsProject">
        /// </seealso>
        public override void PrintValue(StreamWriter os, String space, bool print_decl_p) {
            if (!Project)
                return;
            base.PrintValue(os, space, print_decl_p);
        }


        // --------------- Projection Interface
        /// <summary>Set the state of this variable's projection. <code>true</code> means
        /// that this variable is part of the current projection as defined by
        /// the current constraint expression, otherwise the current projection
        /// for this variable should be <code>false</code>.
        /// </summary>
        /// <param name="state"><code>true</code> if the variable is part of the current
        /// projection, <code>false</code> otherwise.
        /// </param>
        /// <param name="all">This parameter has no effect for this type of variable.
        /// </param>
        /// <seealso cref="CEEvaluator">
        /// </seealso>
        public virtual void SetProject(bool state, bool all) {
            Project = state;
        }

        /// <summary>Set the state of this variable's projection. <code>true</code> means
        /// that this variable is part of the current projection as defined by
        /// the current constraint expression, otherwise the current projection
        /// for this variable should be <code>false</code>. 
        /// </summary>
        /// <param name="state"><code>true</code> if the variable is part of the current
        /// projection, <code>false</code> otherwise.
        /// </param>
        /// <seealso cref="CEEvaluator">
        /// </seealso>
        public virtual void SetProject(bool state) {
            SetProject(state, true);
        }

        /// <summary>Is the given variable marked as projected? If the variable is listed
        /// in the projection part of a constraint expression, then the CE parser
        /// should mark it as <em>projected</em>. When this method is called on
        /// such a variable it should return <code>true</code>, otherwise it
        /// should return <code>false</code>.
        /// </summary>
        /// <returns> <code>true</code> if the variable is part of the current
        /// projections, <code>false</code> otherwise.
        /// </returns>
        /// <seealso cref="CEEvaluator">
        /// </seealso>
        /// <seealso cref="setProject(bool)">
        /// </seealso>
        public virtual bool IsProject() {
            return (Project);
        }


        // --------------- IRelationalOps Interface
        /// <summary>The IRelationalOps interface defines how each type responds to relational
        /// operators. Most (all?) types will not have sensible responses to all of
        /// the relational operators (e.g. DBoolean won't know how to match a regular
        /// expression but DString will). For those operators that are nonsensical a
        /// class should throw InvalidOperatorException.
        /// </summary>
        public virtual bool Equal(BaseType bt) {
            return (Operator.op(ExprParserConstants_Fields.EQUAL, this, bt));
        }

        public virtual bool Not_equal(BaseType bt) {
            return (Operator.op(ExprParserConstants_Fields.NOT_EQUAL, this, bt));
        }

        public virtual bool Greater(BaseType bt) {
            return (Operator.op(ExprParserConstants_Fields.GREATER, this, bt));
        }

        public virtual bool Greater_eql(BaseType bt) {
            return (Operator.op(ExprParserConstants_Fields.GREATER_EQL, this, bt));
        }

        public virtual bool Less(BaseType bt) {
            return (Operator.op(ExprParserConstants_Fields.LESS, this, bt));
        }

        public virtual bool Less_eql(BaseType bt) {
            return (Operator.op(ExprParserConstants_Fields.LESS_EQL, this, bt));
        }

        public virtual bool Regexp(BaseType bt) {
            return (Operator.op(ExprParserConstants_Fields.REGEXP, this, bt));
        }


        // --------------- FileIO Interface

        /// <summary>Set the Synthesized property.</summary>
        /// <param name="state">If <code>true</code> then the variable is considered a
        /// synthetic variable and no part of DODS will ever try to read it from a
        /// file, otherwise if <code>false</code> the variable is considered a
        /// normal variable whose value should be read using the
        /// <code>read()</code> method. By default this property is false.
        /// </param>
        /// <seealso cref="IsSynthesized">
        /// </seealso>
        /// <seealso cref="Read(string,object)">
        /// </seealso>
        public virtual void SetSynthesized(bool state) {
            Synthesized = state;
        }

        /// <summary>Get the value of the Synthesized property.</summary>
        /// <returns> <code>true</code> if this is a synthetic variable,
        /// <code>false</code> otherwise. 
        /// </returns>
        public virtual bool IsSynthesized() {
            return (Synthesized);
        }

        /// <summary>Read a value from the named dataset for this variable. </summary>
        /// <param name="datasetName">String identifying the file or other data store
        /// from which to read a vaue for this variable.
        /// </param>
        /// <param name="specialO">This <code>Object</code> is a goody that is used by Server implementations
        /// to deliver important, and as yet unknown, stuff to the read method. If you
        /// don't need it, make it a <code>null</code>.
        /// </param>
        /// <returns> <code>true</code> if more data remains to be read, otherwise
        /// <code>false</code>. This is an abtsract method that must be implemented
        /// as part of the installation/localization of a DODS server.
        /// </returns>
        /// <exception cref="IOException">@exception EOFException 
        /// </exception>
        public abstract bool Read(String datasetName, Object specialO);


        /// <summary> Server-side serialization for DODS variables (sub-classes of
        /// <code>BaseType</code>).
        /// This does not send the entire class as the Java <code>Serializable</code>
        /// interface does, rather it sends only the binary data values. Other software
        /// is responsible for sending variable type information (see <code>DDS</code>).
        /// 
        /// Writes data to a <code>DataOutputStream</code>. This method is used
        /// on the server side of the DODS client/server connection, and possibly
        /// by GUI clients which need to download DODS data, manipulate it, and
        /// then re-save it as a binary file.
        /// 
        /// </summary>
        /// <param name="sink">a <code>DataOutputStream</code> to write to.
        /// </param>
        /// <exception cref="IOException">thrown on any <code>OutputStream</code> exception. 
        /// </exception>
        /// <seealso cref="BaseType">
        /// </seealso>
        /// <seealso cref="DDS">
        /// </seealso>
        /// <seealso cref="ServerDDS">
        /// </seealso>
        //UPGRADE_TODO: Class 'java.io.DataOutputStream' was converted to 'System.IO.BinaryWriter' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioDataOutputStream'"
        public virtual void Serialize(String dataset, BinaryWriter sink, CEEvaluator ce, Object specialO) {
            if (!IsRead)
                Read(dataset, specialO);

            if (ce.evalClauses(specialO))
                Externalize(sink);
        }
    }
}